import GameData_blxf from "../GameData/GameData";
import { EnumManager_blxf } from "../Manager/EnumManager";
import PageManager_blxf from "../Manager/PageManager";
import { PlatformManager_blxf } from "../Manager/PlatformManager";
import { ConfigModule_blxf } from "./ConfigModule";
import { UtilsModule_blxf } from "./UtilsModule";


const {ccclass, property} = cc._decorator;

/** 货币模块 */
@ccclass
export class NumModule_blxf {

    private constructor () {}

    private static _NumModule_blxf: NumModule_blxf = new NumModule_blxf();

    public static get instance () {
        return this._NumModule_blxf;
    }
    
    /**
     * 获取当前时间
     * @returns 时间戳
     */
    getTime_blxf () {
        let _t = Date.now();
        return _t;
    }

    /**
     * 获取时间字符串
     * @returns 返回时间
     */
    getTimeStr_blxf ( checkTime: number = null ) {
        let _nowTime = checkTime ? checkTime : this.getTime_blxf();
        let _timeStr: string = new Date( _nowTime ).toLocaleDateString();
        return _timeStr;
    }

    // 时间格式化
    getTimeStr2_blxf ( time: number ) {
        let hour: any = Math.floor(time / 3600);
        let mintue: any = Math.floor((time - hour * 3600) / 60);
        let second: any = Math.floor(time - hour * 3600 - mintue * 60);

        var timeStr = '';
        if (hour < 10)
            hour = '0' + hour;
        if (mintue < 10)
            mintue = mintue;
            if (hour > 0 && mintue < 10) mintue = '0' + mintue;
        if (second < 10)
            second = '0' + second;

        if (hour < 1) {
            timeStr = mintue + ':' + second;
        } else {
            timeStr = hour + ':' + mintue + ":" + second;
        }
        return timeStr;
    }

    // 权重
    onWeight_blxf ( arr: any[], attrStr: string = 'Weight', isIndex: boolean = false ) {
        let arr1 = [], arr2 = [], weightArr = [];
        arr.forEach( (item, index) => {
            let _isNaN = isNaN( Number(item[attrStr]) );
            if ( _isNaN ) return;

            arr1.push(index);
            arr2.push(item[attrStr]);
        })
        let len = arr1.length, baseNum = 100;
        for(let i = 0 ; i < len ; i++) {
            let _maxJ = arr2[i] * baseNum;
            for(let j = 0 ; j < _maxJ; j++) {
                weightArr.push(arr1[i]);
            }
        }
        let weightLen = weightArr.length;
        let randomIndex = Math.floor(Math.random() * weightLen);
        let weightItem = weightArr[randomIndex];
        return isIndex ? weightItem : arr[weightItem];
    }

    /**
     * 获取货币类型
     * @param type 1: 金币、2：元宝
     */
    getNumByType ( type: number = 1 ) {
        let _num: number = 0;

        let { NUM_GOLD, NUM_DIAMOND, NUM_PAPER, NUM_PASS } = EnumManager_blxf.gameNumType;
        switch ( Number(type) ) {
            case NUM_GOLD    : _num = GameData_blxf.instance.getGoldNum_blxf();    break;
            case NUM_DIAMOND : _num = GameData_blxf.instance.getDiamondNum_blxf(); break;
            case NUM_PAPER   : _num = GameData_blxf.instance.getPaperNum_blxf(); break;
            case NUM_PASS    : _num = GameData_blxf.instance.getBigPassNum_blxf(); break;
            
        }

        return _num;
    }

    /**
     * 更新货币数量
     * @param type 货币类型 1: 金币、2：元宝
     * @param updateNum 更新货币数
     */
    updateNumByType ( type: number, updateNum: number, inP: cc.Vec3 = cc.v3() ) {
        if ( type === undefined || updateNum === undefined ) {
            UtilsModule_blxf.instance.Log_blxf(`参数有误 type & updateNum ==> ${type} & ${updateNum}`);
            return;
        }

        if ( typeof(updateNum) != 'number' ) {
            return UtilsModule_blxf.instance.Log_blxf(`更新货币数量参数类型错误！！！`, 2);
        }

        let { NUM_GOLD, NUM_DIAMOND, NUM_PAPER } = EnumManager_blxf.gameNumType;
        switch ( type ) {
            case NUM_GOLD   : GameData_blxf.instance.updateGoldNum_blxf( updateNum ); break;
            case NUM_DIAMOND : GameData_blxf.instance.updateDiamondNum_blxf( updateNum );
                // OpenDataContext_blxf.setShopNum_blxf();

                // 更新财富值
                updateNum > 0 && this.updateWealthNum_blxf();
                updateNum > 0 && cc.game.emit('onCheckAutoUnlockTarget_blxf');
                break;
            case NUM_PAPER : GameData_blxf.instance.updatePaperNum_blxf( updateNum ); break;
        }

        // 图标动画
        updateNum > 0 && PageManager_blxf.instance.onIconAnimation_blxf( type, updateNum, inP );
    }

    // 更新财富值
    async updateWealthNum_blxf () {
        let { NUM_DIAMOND } = EnumManager_blxf.gameNumType;
        let _wealthNum: number = this.getNumByType( NUM_DIAMOND );
        let _isUpload: boolean = !!ConfigModule_blxf.instance.avatarUrl;
        if ( !_isUpload ) return;

        await PlatformManager_blxf.instance.updateWealthNum_blxf( _wealthNum );
    }

    /**
     * 检测货币是否足够
     * @param type 货币类型
     * @param checkNum 检测货币数
     * @returns 是否足够
     */
    onCheckNum_blxf ( type: number, checkNum: number, isBtn: boolean = false ) {
        let { NUM_GOLD } = EnumManager_blxf.gameNumType;
        let _iconNum: number = this.getNumByType( type );
        let _isNum: boolean = this.onCompareNum_blxf( _iconNum, checkNum, true );

        let tipsMsg = `${ type == NUM_GOLD ? '金币' : '粮票' }不足`;
        switch ( Number(type) ) {
            case 1 : tipsMsg = `金币不足`; break;
            case 2 : tipsMsg = `财富达到${checkNum}可解锁`; break;
            case 8 : tipsMsg = `第${checkNum}关解锁`; break;
        }
        !_isNum && isBtn && type == NUM_GOLD && cc.game.emit('loadGoldVideoPanel_blxf');
        // !_isNum && isBtn && PageManager_blxf.instance.loadComonTipsPanel_blxf({ tipsMsg, zIndex: 999 });
        return _isNum;
    }

    /**
     * 比较两个数大小
     * @param num1 被比较数
     * @param num2 比较数
     * @param isEqual 是否相等
     * @returns 返回比较值
     */
    onCompareNum_blxf ( num1: number, num2: number, isEqual: boolean = false ) {
        let _isNum: boolean;
        if ( num1 === undefined || num2 === undefined ) {
            UtilsModule_blxf.instance.Log_blxf(`参数有误 num1 & num2 ==> ${num1} & ${num2}`);
            return _isNum;
        }

        _isNum = num1 - num2 > 0 || isEqual && num1 == num2;
        return _isNum;
    }

    /** 获取两个坐标距离 */
    getDistance (p1: cc.Vec3, p2: cc.Vec3 ) {
        const dx = p2.x - p1.x;
        const dy = p2.y - p1.y;
        return Math.sqrt(dx * dx + dy * dy);
    }

    /**
     * 获取动画时间
     * @param skeleton spine动画
     * @param animationName 动画名
     * @returns 返回动画时间
     */
    onAnimationTime_blxf ( skeleton: sp.Skeleton, animationName: string ) {
        let skeletonData = skeleton['_N$skeletonData'];
        if (!skeletonData || !skeletonData['_skeletonCache']) return;

        let animations = skeletonData['_skeletonCache']['animations'];
        if (!animations) return;

        let animationData = animations.find(item => item.name == animationName);
        return animationData ? animationData.duration : null;
    }
    
    /** 随机数组元素 */
    onRandomListItem_blxf ( list: any[] ) {
        // cc.log('_randomItem >1>', [...list]);
        list.sort((a, b) => Math.random() - 0.5);

        let _randomItem: any = list[0];

        // cc.log('_randomItem >2>', _randomItem, list);
        return _randomItem;
    }

    /** 百分比转化成小数 */
    changeNum_blxf ( percent: string ) {
        let [ _n ] = percent.split('%');
        let _num: number = Number( _n ) / 100;
        
        return _num;
    }

    /** 小数转化百分比 */
    changePercent_blxf ( ratio: number ) {
        let _percentNum: number = Math.floor( ratio * 100 );
        let _percentStr: string = `${_percentNum}%`;
        return _percentStr;
    }

    /**
     * 是否有可能(百分比制)
     * @param percent 百分比
     */
    isChance_blxf ( percent: string ) {
        if ( !percent || typeof(percent) != 'string' ) return;
        if ( !percent.includes('%') ) return;

        let _checkNum: number = this.changeNum_blxf( percent );
        let _isChance: boolean = this.isRatio_blxf( _checkNum );

        return _isChance;
    }

    /**
     * 是否有可能(小数制)
     * @param ratioNum 
     */
    isRatio_blxf ( ratioNum: number ) {
        if ( ratioNum === undefined || typeof(ratioNum) != 'number' ) return;

        let _isChance: boolean = ratioNum > Math.random();

        return _isChance;
    }


    /**
     * 计算字符串公式结果
     * @param str 公式字符串 
     * @param replaceStr 替换字符串
     * @returns 返回结果
     */
    onEval_blxf (str: string = '(7*level*level+5*level)*120', replaceStr: string, replaceNum: any, isFloor: boolean = false) {
        if (str == '' || !str) return 0;
        // cc.log('str =', str);
         
        let result: any;

        // 替换变量
        switch ( replaceStr ) {
            case 'N'  : str = str.replace(/N/g, replaceNum); break;
            case 'LV' : str = str.replace(/LV/g, replaceNum); 
        }
        
        // cc.log('str =', str, str.length);

        // 带()，先计算()里的值
        let ind1 = str.indexOf('(');
        let ind2 = str.indexOf(')');
        if (ind1 != -1 && ind2 != -1) {
            let _str = str.substring(ind1+1, ind2);
            // cc.log('_str =', _lv, _str, _str.length);
            let _result: any = this.onParseStr_blxf(_str);
            str = str.replace(`(${_str})`, _result);
        }

        if (str.includes('(')) {
            // cc.log('str =', str)
            return this.onEval_blxf(str, replaceStr, replaceNum);
        }
        
        // 计算总值
        result = this.onParseStr_blxf(str);
        // if (cc.sys.isBrowser) result_eval = eval(str);
        // cc.log('result =>', result);

        return isFloor ? result : Math.round(result);
    }

    // 解析字符串公式
    onParseStr_blxf ( str ) {
        let arr = str.split('+');
        arr = arr.map( item => {
            if (item.includes('*')) {
                let num = 1;
                let nums = item.split('*');
                nums.forEach( itemNum => num *= Number(itemNum));
                return num;
            }
            return Number(item);
        })
        let totalNum = 0;
        arr.forEach(_num => totalNum += Number(_num));
        // cc.warn('onParseStr =2=', str, arr, totalNum);
        return totalNum;
    }

    /**
     * 解析配置数据
     * @param cfgData 配置数据
     * @param level 等级
     */
    onParseCfgData_blxf ( cfgData: any, level: number = 0 ) {
        let { Condition, ConsumeStr, RewardStr, PriceStr, MaxNum, SaleAddNum  } = cfgData;
        Condition = Condition || '', RewardStr = RewardStr || '', PriceStr = PriceStr || '';
        MaxNum = MaxNum || '', SaleAddNum = SaleAddNum || '';
        
        let [ checkType, checkNum ] = Condition.split('_');
        let [ consumeType, consumeNum ] = ConsumeStr.split('_');
        let [ rewardType, rewardNum ] = RewardStr.split('_');
        let [ priceType, priceNum ] = PriceStr.split('_');
        checkType = Number(checkType), consumeType = Number(consumeType), rewardType = Number(rewardType), priceType = Number(priceType);

        if ( checkNum ) checkNum     = this.onEval_blxf( checkNum, 'LV', level );
        if (consumeNum ) consumeNum  = this.onEval_blxf( consumeNum, 'LV', level );
        if (rewardNum ) rewardNum    = this.onEval_blxf( rewardNum, 'LV', level );
        if ( priceNum ) priceNum     = this.onEval_blxf( priceNum, 'LV', level );
        if ( MaxNum ) MaxNum         = this.onEval_blxf( MaxNum, 'LV', level );
        if ( SaleAddNum ) SaleAddNum = this.onEval_blxf( SaleAddNum, 'LV', level );

        Object.assign( cfgData, { checkType, checkNum, consumeType, consumeNum, rewardType, rewardNum, MaxNum, SaleAddNum, priceType, priceNum });
    }
}
